package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.boot.env.YamlPropertySourceLoader;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;

import java.io.IOException;

/**
 * 自定义环境后处理器，用于加载额外的YAML配置文件到Spring环境中
 * 功能：从类路径加载指定的YAML文件，并将其转换为PropertySource添加到环境变量中
 */
public class MyEnvironmentPostProcessor implements EnvironmentPostProcessor {

    // 用于加载YAML属性的专用加载器
    private final YamlPropertySourceLoader loader = new YamlPropertySourceLoader();

    /**
     * 环境后处理方法，将自定义YAML配置加载到Spring环境中
     * @param environment 当前应用的可配置环境对象
     * @param application 当前正在运行的Spring应用对象
     */
    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
        // 从类路径加载指定位置的YAML配置文件
        Resource path = new ClassPathResource("com/example/myapp/config.yml");
        // 将YAML文件解析为属性源对象
        PropertySource<?> propertySource = loadYaml(path);
        // 将自定义属性源添加到环境变量列表末尾
        environment.getPropertySources().addLast(propertySource);
    }

    /**
     * 加载YAML格式的配置文件
     * @param path 表示YAML文件资源的Resource对象
     * @return 解析后的属性源对象
     * @throws IllegalStateException 如果读取或解析YAML文件时发生错误
     */
    private PropertySource<?> loadYaml(Resource path) {
        // 验证文件是否存在
        Assert.isTrue(path.exists(), () -> "'path' [%s] must exist".formatted(path));
        try {
            // 使用YAML属性加载器读取并解析文件内容
            return this.loader.load("custom-resource", path).get(0);
        }
        catch (IOException ex) {
            // 包装IO异常为非法状态异常，包含原始异常信息
            throw new IllegalStateException("Failed to load yaml configuration from " + path, ex);
        }
    }

}